package carGeneration;

import java.util.Random;
import org.objectweb.proactive.Body;
import org.objectweb.proactive.ProActive;
import org.objectweb.proactive.Service;
import org.objectweb.proactive.ext.migration.Destination;
import org.objectweb.proactive.ext.migration.MigrationStrategyImpl;

import Bloques.*;
import event.*;
import principal.AgentMessageReceiver;
import principal.StreetControllerAgent;
import principal.agentFrame;


public class CarGeneratorAgent implements org.objectweb.proactive.RunActive,
java.io.Serializable {
	private boolean onItinerary = false;
	private boolean initialized;
	private transient agentFrame myFrame;
	private AgentMessageReceiver controler;
	private CarGeneratorAgent otherCarGeneratorAgent;
	private javax.swing.ImageIcon face;
	private org.objectweb.proactive.ext.migration.MigrationStrategy myStrategy;
	private org.objectweb.proactive.ext.migration.MigrationStrategyManager myStrategyManager;
	private int index;
	private String name;
	private String[] itinerary;
        int VERDE = 1;
	int ROJO = 0;
	int AMBAR =3;

	int SE =1 ; //Stop Event
	int CE =  2;//Cross Event
	int LCE = 3; //Light Change Event
	
	int CLE = 5; //Change Lane Event
	int CLEE = 6; //Change Lane End Event
	int ALE = 7; //Arrival Link Event
	int LLE = 8; //Leave Link Event
	int BE = 9; //Begin Event
	int AE= 10; //Arrival Event
	int WSE = 11; //Warning Event, as a stop event, but dont stop
	int WBE = 12; // warning Event, as a begin event, but actually for a dont stop event
        

    private StreetControllerAgent streetControllerAgent;

    private int n;

    private double t;
	
	public CarGeneratorAgent() {
	}

	public CarGeneratorAgent(Integer ind) {
		this.index = ind.intValue();
		this.name = "CarGenerator Agent" + index;
		
	}

	public void loop() {
		rebuild();
	}

	public void rebuild() {
		Body body = ProActive.getBodyOnThis();
		myFrame = new agentFrame(face, body.getNodeURL(), index);
		
		sendMessageToControler("I just got in node " +
				ProActive.getBodyOnThis().getNodeURL());
		try {
			Thread.sleep(4000);
		} catch (InterruptedException e) {
		}
	}

	public void clean() {
		if (myFrame != null) {
			myFrame.dispose();
			myFrame = null;
		}
	}

	public String toString() {
		return this.name;
	}

	public void initialize(String[] s) {
		try {
			//With this we can load the image from the same location than
			//the classes
			ClassLoader cl = this.getClass().getClassLoader();
			//java.net.URL u = cl.getResource(
			//      "org/objectweb/proactive/examples/penguin/PenguinSmall.jpg");
			java.net.URL u = cl.getResource("Resources/EMPRESA.jpg");
			face = new javax.swing.ImageIcon(u);
		} catch (Exception e) {
			e.printStackTrace();
		}
		myStrategyManager = new org.objectweb.proactive.ext.migration.MigrationStrategyManagerImpl((org.objectweb.proactive.core.body.migration.Migratable) org.objectweb.proactive.ProActive.getBodyOnThis());
		myStrategyManager.onDeparture("clean");
		myStrategy = new MigrationStrategyImpl();
		itinerary = s;
		for (int i = 0; i < s.length; i++)
			myStrategy.add(s[i], null);
	}

	public void setControler(AgentMessageReceiver c) {
		this.controler = c;
		this.initialized = true;
	}

	public void setOther(CarGeneratorAgent carGenerator) {
		this.otherCarGeneratorAgent = carGenerator;
	}

	public Destination nextHop() {
		Destination r = myStrategy.next();
		if (r == null) {
			myStrategy.reset();
			r = myStrategy.next();
		}
		return r;
	}

	public void runActivity(Body b) {
		Service service = new Service(b);
		if (!initialized) {
			service.blockingServeOldest();
		}
		rebuild();
		Destination r = null;
		
		
               
		//first we empty the RequestQueue
		//int id,int position,String name,int firstDelay
		//Car kdvu = new Car(2000,0,"MiCarro",300);
		Car car;
                n = 0;
                t = 0;
                int poisson = 0;
		while (b.isActive()) {
			while (service.hasRequestToServe()) {
				service.serveOldest();
			}
			if (onItinerary) {
               
                        poisson = this.Poisson(6.0);
                        while(poisson == 0)
                           poisson = Poisson(6.0);
                                     
                            t = t+poisson;
                            //System.out.println("Se puso un evento AE a las "+t+"para el carrito "+n);
                            // ponerEvento(int segment,double evTime,int typeEvent, Object objectId, double eventPosition,int desiredStatus, int lane){
                            car = new Car(n,0.0,"car "+n,2.0,40000.0,2.0);    
                            streetControllerAgent.ponerEvento(0,t,AE,car,0,AMBAR,0);
                            n++;
                            car = new Car(n,0.0,"car "+n,2.0,40000.0,2.0);    
                            streetControllerAgent.ponerEvento(35,t,AE,car,0,AMBAR,0);
                            n++;	
                              
                              
                              
                              if(n == 1000){
                                  onItinerary = false;
                                  this.sendMessageToControler("2");
                                  System.out.println("Finish carGenerator");
                                  
                              }
                               // else
                                   // t = t+15;
               
                /*        try {
                    Thread.sleep(100);   
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }*/
                        }
		
			 else {
				// service.blockingServeOldest();
			}
		}
	}

	public String[] getItinerary() {
		return itinerary;
	}

	public void setItinerary(String[] newItinerary) {
		sendMessageToControler("I changed my itinerary", java.awt.Color.blue);
		myStrategy = new MigrationStrategyImpl();
		itinerary = newItinerary;
		for (int i = 0; i < newItinerary.length; i++)
			myStrategy.add(newItinerary[i], null);
	}

	public void start(StreetControllerAgent streetControllerAgent) {
		sendMessageToControler("I am starting my itinerary",
				new java.awt.Color(0, 150, 0));
		myStrategy.reset();
		onItinerary = true;
                this.streetControllerAgent = streetControllerAgent;
	}
	public void listo(){
		onItinerary = true;
		System.out.println("listo");
	}
	public void suspend() {
		if (!onItinerary) {
			sendMessageToControler("I'm already suspended");
		} else {
			sendMessageToControler("I suspended my itinerary",
					java.awt.Color.red);
			onItinerary = false;
		}
	}

	public void resume() {
		if (onItinerary) {
			sendMessageToControler("I'm already on my itinerary");
		} else {
			sendMessageToControler("I'm resuming my itinerary",
					new java.awt.Color(0, 150, 0));
			onItinerary = true;
		}
	}

	public String call() {
		return "[" + name + "] : I am working on node " +
		ProActive.getBodyOnThis().getNodeURL();
	}

	public void chainedCall() {
		if (otherCarGeneratorAgent != null) {
			sendMessageToControler("I'm calling my peer agent");
			otherCarGeneratorAgent.chainedCall();
		} else {
			sendMessageToControler("I don't have a peer agent to call");
		}
	}

	private void sendMessageToControler(String message) {
		if (controler != null) {
			controler.receiveMessage(message);
		}
	}

	private void sendMessageToControler(String message, java.awt.Color color) {
		if (controler != null) {
			controler.receiveMessage("[" + name + "] : " + message, color);
		}
	}
        public int Poisson(double lambda){
            Random rand = new Random();
            int k = 0;
            double A = 1;
            double dummy;
            for(k =1;k<= 1000;k++){
                dummy = 0;
                while(dummy <= 0 || dummy >= 1) dummy = rand.nextDouble();
                A = A * dummy;
                if ( A < Math.exp(-lambda)) return k -1;
                
            }
            return k-1;
        }
	
	
}


